﻿using System;
using System.Collections.Generic;

namespace JH
{
    /// <summary>
    ///  固定容量的容器接口
    /// </summary>
    // ReSharper disable once PossibleInterfaceMemberAmbiguity 
    // 约定严格显示实现接口成员，忽略接口二义性
    public interface IFixedContainer<T> : IReadOnlyList<T>, IList<T>
    {
        /// <summary>
        ///  溢出模式
        /// </summary>
        public OverflowMode Mode { get; }

        /// <summary>
        ///  容器的最大容量
        /// </summary>
        public int MaxSize { get; }

        /// <summary>
        ///  当元素因为存储容量满了，添加新元素而被丢弃时触发
        /// </summary>
        public event Action<T> OnItemDiscard;

        /// <summary>
        ///  根据溢出行为枚举，获取需要丢弃的元素
        /// </summary>
        /// <remarks>请不要调用此函数</remarks>>
        public T GetDiscardItem();

        /// <summary>
        ///  引发丢弃事件
        /// </summary>
        /// <remarks>请不要调用此函数</remarks>>
        public void InvokeEvent(T item);
    }

    public static class FixedContainerExtensions
    {
        /// <summary>
        ///  处理溢出
        /// </summary>
        public static void HandleOverflow<T>(this IFixedContainer<T> container)
        {
            // 获取容量
            var count = ((IReadOnlyCollection<T>)container).Count;

            // 如果当前容量未满，不需要处理溢出
            if (count != container.MaxSize) return;

            // 如果移除模式为抛出异常，则直接抛出
            if (container.Mode == OverflowMode.ThrowException)
                throw new InvalidOperationException($"容量已满，无法添加新元素！当前最大容量为 {container.MaxSize}，" +
                                                    $"当前元素数量为 {count}。");

            // 获取丢弃元素的逻辑
            var discardedItem = container.GetDiscardItem();

            // 移除指定索引处的元素
            container.Remove(discardedItem);

            // 引发事件
            container.InvokeEvent(discardedItem);
        }
    }
}